home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 3 / Info_Mac_1994-01.iso / Development / Source / Mailcheck Source / drvr src / mmc_core.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-15  |  15.9 KB  |  723 lines  |  [TEXT/KAHL]

  1. /*
  2.  *
  3.  * mac mail check network checking module
  4.  * by Aaron Wohl (aw0g+@andrew.cmu.edu) jul 1990
  5.  * Carnegie-Mellon University
  6.  * Pittsburgh, PA 15213-3890
  7.  * (412)-268-5032
  8.  *
  9.  */
  10.  
  11. #include "MacTCPCommonTypes.h"
  12. #include "UDPPB.h"
  13. #include "gms.h"
  14. #include "mmc_core.h"
  15. #include "mmc_notify.h"
  16. #include "mmc_core_private.h"
  17. #include "mmc_config.h"
  18.  
  19. #include <string.h>
  20.  
  21. mmc_gl_t mmc_gl;
  22.  
  23. /*
  24.  * extended io pb with some of our variables on the end
  25.  */
  26. struct xpb_R {
  27.     union {
  28.         ioParam iopb;
  29.         UDPiopb pb;
  30.     }x;
  31.     void (*success_rtn)(struct xpb_R *pb);        /*routines for when io finishes*/
  32.     int state_name;                /*MCE_ name of what we are trying to do*/
  33.     
  34. };
  35. typedef struct xpb_R xpb,*xpb_pt;
  36.  
  37. static struct {
  38.     StreamPtr udp_stream; /*upd port*/
  39.     xpb mainpb;            /*used for all calls except release*/
  40.     /*
  41.      * declare a smaller than max gms_mail_status since we never send
  42.      * real long usernames
  43.      */
  44.     long gms_send_space[(GMS_nameoffset+MMC_uname_len*2+12)/sizeof(long)];
  45. } ip_gl;
  46. #define GMS_send ((gms_mail_status_pt)(&ip_gl.gms_send_space))
  47.  
  48. static void mmc_start(void);
  49. static void poll_server(void);
  50.  
  51. /*
  52.  * mactcp doesn't seem to allow a smaller buffer
  53.  */
  54. #define UDP_BUF_SIZE (4000)
  55.  
  56. /*
  57.  * remember last error
  58.  */
  59. LDEF(void set_error(int mce_kind,int syserrcode))
  60. {
  61.   mmc_gl.cs.mmc_last_err_kind=mce_kind;
  62.   mmc_gl.cs.mmc_last_err_syserr=syserrcode;
  63.   if(mmc_gl.cps.ev[EV_error].ev_event!=mmc_note_new_error) {
  64.     mmc_note_no_mail();
  65.     set_event(EV_error,mmc_note_new_error,ERROR_ANNOUNCE_TIME);
  66.   }
  67. }
  68.  
  69. /*
  70.  * an error that nukes the connection occured
  71.  * to help in debugging and notifying the user
  72.  */
  73. LDEF(void set_conn_err(int mce_kind,int syserrcode))
  74. {
  75.   set_error(mce_kind,syserrcode);
  76.   set_event(EV_retrans,mmc_start,RESTART_ON_ERROR_TIME);
  77. }
  78.  
  79. /*
  80.  * set the parts of a udp iopb that are
  81.  * the same for all calls
  82.  * note that PBOpen doesn't take a udp iopb
  83.  */
  84. LDEF(void init_udp_pb(UDPiopb *pb,int code))
  85. {
  86.     INIT_CPB(*pb,mmc_gl.cps.ip_ref,code);
  87.       pb->udpStream = ip_gl.udp_stream;
  88.       return;
  89. }
  90.  
  91. /*
  92.  * invalidate things that depend on current host
  93.  */
  94. LDEF(void invalide_current_host(void))
  95. {
  96.   mmc_gl.cps.change_count=0;
  97. }
  98.  
  99. /*
  100.  * close down, will auto restart if MMC_want_open
  101.  */
  102. LDEF(void mmc_close(void))
  103. {
  104.   UDPiopb pb;
  105.   int err;
  106.  
  107.   /*
  108.    * releasing the udp port below will abort any pending io
  109.    * so don't leave the pending flag set
  110.    */
  111.   gTURN_OFF_FLAGS(MCS_io_pending);
  112.   set_event(EV_retrans,mmc_start,RESTART_ON_ERROR_TIME);
  113.   mmc_note_no_mail();
  114.  
  115.   if((mmc_gl.cps.ip_ref!=0)&&
  116.     (ip_gl.udp_stream!=0)) {
  117.     init_udp_pb(&pb,UDPRelease);
  118.       pb.csParam.create.rcvBuff = mmc_gl.cps.udp_buf;
  119.       pb.csParam.create.rcvBuffLen = UDP_BUF_SIZE;
  120.  
  121.     ip_gl.udp_stream=0;            /*eithor way say we are done*/
  122.       err=PBControl((void*)&pb,FALSE);    /*do this syncronous, get it done*/
  123.  
  124.     if(err!=0)
  125.         set_conn_err(MCE_UDP_REL,err);
  126.     mmc_gl.cps.packet_waiting=0;
  127.    }
  128.  
  129.   mmc_gl.cps.ip_ref=0;            /*open the driver again if we gTURN on again*/
  130. }
  131.  
  132. /*
  133.  * close down, don't try to restart
  134.  */
  135. LDEF(void mmc_shutdown(void))
  136. {
  137.   strcpy(mmc_gl.cs.mmc_text_state,"MailChecking is shut off");
  138.   mmc_close();
  139.   set_event(EV_retrans,EV_NOTHING,0);
  140. }
  141.  
  142. /*
  143.  * set a perminante error that will shutdown
  144.  * with no automatic retry
  145.  */
  146. LDEF(void set_perm_error(int mce_kind,int syserrcode))
  147. {
  148.     mmc_shutdown();
  149.     set_conn_err(mce_kind,syserrcode);
  150. }
  151.  
  152. void mmc_uninit(void)
  153. {
  154.     mmc_shutdown();
  155.     if(mmc_gl.cps.udp_buf!=0)
  156.         DisposPtr(mmc_gl.cps.udp_buf);
  157.     mmc_note_uninit();
  158.     memset(&mmc_gl,0,sizeof(mmc_gl));
  159.     memset(&ip_gl,0,sizeof(ip_gl));
  160.     return;
  161. }
  162.  
  163. /*
  164.  * io failure handler/routines to close stream
  165.  */
  166. LDEF(void mmc_io_fail(xpb_pt pb,int state))
  167. {
  168.   gTURN_OFF_FLAGS(MCS_io_pending);
  169.   mmc_close();
  170.   set_conn_err(state,pb->x.pb.ioResult);
  171. }
  172.  
  173. /*
  174.  * see if a pb has finished
  175.  */
  176. LDEF(void poll_pb(xpb_pt pb))
  177. {
  178.  do {
  179.     int done=pb->x.pb.ioResult;
  180.     if(done==1)        /*still running?*/
  181.         return;        /* yes*/
  182.     gTURN_OFF_FLAGS(MCS_io_pending);
  183.     if(done==0) {
  184.         (*(pb->success_rtn))(pb);
  185.         if(gFLSET(MCS_io_pending))
  186.           continue;
  187.     } else
  188.         mmc_io_fail(pb,pb->state_name);
  189.  } while(FALSE);
  190. }
  191.  
  192. /*
  193.  * wait for io to finish then enter a new state
  194.  */
  195. LDEF(void finish_io(
  196.     xpb_pt pb,
  197.     int initial_result,
  198.     void (*success_rtn)(),
  199.     int description))
  200. {
  201.     pb->success_rtn=success_rtn;
  202.     pb->state_name=description;
  203.     gTURN_ON_FLAGS(MCS_io_pending);
  204.     if(initial_result<0)
  205.         mmc_io_fail(pb,pb->state_name);
  206.     else
  207.         poll_pb(pb);
  208. }
  209.  
  210. LDEF(void IOCompletionProc(struct UDPiopb *iopb))
  211. {
  212. }
  213.  
  214. /*
  215.  * do a macip async call
  216.  */
  217. LDEF(void do_macip_async(
  218.     xpb_pt pb,
  219.     int code,
  220.     void (*success_rtn)(),
  221.     int description))
  222. {
  223.   init_udp_pb(&pb->x.pb,code);
  224.   pb->x.pb.ioCompletion=IOCompletionProc;
  225.   finish_io(pb,PBControl((void*)pb,TRUE),success_rtn,description);
  226. }
  227.  
  228. LDEF(void act_idle(xpb_pt pb))
  229. {
  230. }
  231.  
  232. LDEF(update_ask_time(void))
  233. {
  234.     int delay;
  235.     delay=imax(ABS_MIN_POLL,mmc_gl.cps.server_poll);
  236.     delay=imin(delay,ABS_MAX_POLL);
  237.     set_event(EV_retrans,poll_server,POLL_TIME);
  238.     mmc_gl.cps.unans_queries=0;
  239. }
  240.  
  241. LDEF(void decode_recv(gms_mail_status_pt gm,char *new_text))
  242. {
  243.     int ch0=((gm->gms_change_count0!=0)&&
  244.         (mmc_gl.cps.change_count!=gm->gms_change_count0)&&
  245.         (strcmp(mmc_gl.cs.mmc_text_state,new_text)!=0));
  246.     int prev_flags=gm->gms_flags;
  247.     long new_flags;
  248.  
  249.     mmc_gl.cps.change_count=gm->gms_change_count0;
  250.     mmc_gl.cps.server_poll=
  251.       imin(ABS_MAX_POLL,imax(gm->gms_poll_time,ABS_MIN_POLL));
  252.     mmc_gl.cs.mmc_remind_time=
  253.       imin(2*HOURS,imax(MIN_REMIND,mmc_gl.cs.mmc_remind_time));
  254.  
  255.     update_ask_time();
  256.     strcpy(mmc_gl.cs.mmc_text_state,new_text);
  257.  
  258.     /*
  259.      * if we know knothing is going on for certain,
  260.      * don't give a spurious error as soon as the
  261.      * the net flakes out
  262.      */
  263.     if((gm->gms_flags&gms_fl_error)!=0)
  264.       set_error(MCE_REM_ERR,0);
  265.     else {
  266.       mmc_note_no_error();
  267.       if((gm->gms_flags&gms_fl_mail)==0)
  268.         mmc_note_no_mail();
  269.       else if(ch0)
  270.         mmc_note_new_mail();
  271.       else
  272.           mmc_note_old_mail();
  273.     }
  274. }
  275.  
  276. LDEF(void gms_read(mmc_read_result_pt rr))
  277. {
  278.     long buf[(GMS_nameoffset+sizeof(long))/sizeof(long)];
  279.     register gms_mail_status_pt gm= (gms_mail_status_pt)&buf;
  280.     int text_len=rr->buf_size-GMS_nameoffset-1;
  281.     char *new_text=rr->buf+GMS_nameoffset;
  282.  
  283.     if((rr->hostn!=HNUM0)&&
  284.        (rr->hostn!=HNUM1)&&
  285.        (rr->hostn!=deb_HNUM)) {
  286.            mmc_gl.cps.last_rcv_error=1;
  287.         return;
  288.     }
  289.  
  290.     if(rr->portn!=MMW_port) {
  291.            mmc_gl.cps.last_rcv_error=2;
  292.         return;
  293.     }
  294.  
  295.     if((rr->buf_size < (GMS_nameoffset+1))) {
  296.            mmc_gl.cps.last_rcv_error=3;
  297.         return;
  298.     }
  299.  
  300.     mmc_gl.cps.unans_queries=0;
  301.  
  302.     /*
  303.      * make a copy get proper alignment of longs
  304.      */
  305.     memcpy(gm,rr->buf,GMS_nameoffset);
  306.  
  307.     if(gm->gms_vers_maj!=GMS_VERS_MAJ) {
  308.         set_perm_error(MCE_TOO_OLD,0);
  309.         return;
  310.     }
  311.  
  312.  
  313.     if(rr->buf_size > GMS_max_size) {
  314.            mmc_gl.cps.last_rcv_error=4;
  315.         return;
  316.     }
  317.  
  318.     if((*(rr->buf+rr->buf_size-1))!=0) {
  319.            mmc_gl.cps.last_rcv_error=5;
  320.         return;
  321.     }
  322.  
  323.     if(strlen(new_text)!=(rr->buf_size-1-GMS_nameoffset)) {
  324.            mmc_gl.cps.last_rcv_error=6;
  325.         return;
  326.     }
  327.  
  328.     if((*new_text)==0)
  329.         strcpy(mmc_gl.cs.mmc_text_state,"[zero length message]");
  330.  
  331.     decode_recv(gm,new_text);
  332. }
  333.  
  334. LDEF(void act_read_done(xpb_pt pb))
  335. {
  336.   mmc_read_result rr;
  337.  
  338.   mmc_gl.cps.packet_waiting--;
  339.  
  340.   rr.buf=pb->x.pb.csParam.receive.rcvBuff;
  341.   rr.buf_size=pb->x.pb.csParam.receive.rcvBuffLen;
  342.   rr.portn=pb->x.pb.csParam.receive.remotePort;
  343.   rr.hostn=pb->x.pb.csParam.receive.remoteHost;
  344.  
  345.   gms_read(&rr);                            /*process a read gms packet*/
  346.  
  347.   do_macip_async(pb,UDPBfrReturn,act_idle,MCE_UDP_REL);
  348. }
  349.  
  350. LDEF(void act_read(xpb_pt pb))
  351. {
  352.   memset(pb,0,(long)sizeof(*pb));
  353.   pb->x.pb.csParam.receive.timeOut = 0;            /*wait for a packet to come in forever*/
  354.   pb->x.pb.csParam.receive.userDataPtr = (Ptr)&mmc_gl;
  355.   do_macip_async(pb,UDPRead,act_read_done,MCE_UDP_READ);
  356. }
  357.  
  358. /*
  359.  * routine called when something happens to a udp port
  360.  */
  361. LDEF(pascal void myUDPNotifyProc(
  362.         StreamPtr udpStream, 
  363.         unsigned short eventCode, 
  364.         mmc_gl_t_pt agl,
  365.         struct ICMPReport *icmpMsg))
  366. {
  367.     if (eventCode==UDPDataArrival)
  368.         agl->cps.packet_waiting++;
  369. }
  370.  
  371. /*
  372.  * make a stream
  373.  */
  374. LDEF(mmc_open_mactcp(void))
  375. {
  376.   xpb_pt pb=&ip_gl.mainpb;
  377.   memset(pb,0,(long)sizeof(*pb));
  378.   pb->x.iopb.ioNamePtr = (StringPtr)"\p.IPP";
  379.   if((pb->x.pb.ioResult=PBOpen((void*)pb,FALSE))!=0) {
  380.     mmc_io_fail(pb,MCE_MACTCP);
  381.     return;
  382.   }
  383.   mmc_gl.cps.ip_ref=pb->x.iopb.ioRefNum;
  384.  
  385.   memset(pb,0,(long)sizeof(*pb));
  386.   pb->x.pb.csParam.create.rcvBuff = mmc_gl.cps.udp_buf;
  387.   pb->x.pb.csParam.create.rcvBuffLen = UDP_BUF_SIZE;
  388.   pb->x.pb.csParam.create.notifyProc = (UDPNotifyProc)myUDPNotifyProc;
  389.   pb->x.pb.csParam.create.userDataPtr = (Ptr)&mmc_gl;
  390.   pb->x.pb.csParam.create.localPort=0;
  391.   init_udp_pb(&pb->x.pb,UDPCreate);
  392.   if((pb->x.pb.ioResult=PBControl((void*)pb,FALSE))!=0) {
  393.     mmc_io_fail(pb,MCE_UDP_CREATE);
  394.     return;
  395.   }
  396.  
  397.   ip_gl.udp_stream=pb->x.pb.udpStream;
  398.   set_event(EV_retrans,poll_server,0);
  399. }
  400.  
  401. /*
  402.  * open the mac ip driver
  403.  */
  404. LDEF(void mmc_start(void))
  405. {
  406.   if(ip_gl.udp_stream==0)
  407.     mmc_open_mactcp();
  408.   else
  409.     set_event(EV_retrans,poll_server,0);
  410. }
  411.  
  412. LDEF(void gms_send(xpb_pt pb))
  413. {
  414.     static wdsEntry pentry[2];
  415.     pentry[0].length=GMS_real_size(*GMS_send);
  416.     pentry[0].ptr=(Ptr)GMS_send;
  417.     pentry[1].length=0;
  418.     pentry[1].ptr=0L;
  419.       memset(pb,0,(long)sizeof(*pb));
  420.       if(gFLSET(MCS_debug))
  421.          pb->x.pb.csParam.send.remoteHost = deb_HNUM;
  422.     else
  423.          pb->x.pb.csParam.send.remoteHost = (mmc_gl.cps.cur_host)?HNUM0:HNUM1;
  424.        pb->x.pb.csParam.send.remotePort = MMW_port;
  425.        pb->x.pb.csParam.send.wdsPtr = (Ptr)&pentry;
  426.        pb->x.pb.csParam.send.checkSum = TRUE;
  427.        pb->x.pb.csParam.send.sendLength = pentry[0].length;
  428.       do_macip_async(pb,UDPWrite,act_idle,MCE_UDP_WRITE);
  429. }
  430.  
  431. /*
  432.  * choose a server.  perhaps the current one doesn't like us
  433.  */
  434. LDEF(void pick_server(void))
  435. {
  436.     if(mmc_gl.cps.unans_queries++ < NUM_FAST_RETRIES)
  437.         return;
  438.  
  439.     mmc_note_no_mail();
  440.     set_error(MCE_TIMEOUT,0);
  441.  
  442.     if((mmc_gl.cps.unans_queries%NUM_FAST_RETRIES)!=0)
  443.         return;
  444.  
  445.     invalide_current_host();
  446.  
  447.     if((++mmc_gl.cps.cur_host)>=NUM_serv_hosts)
  448.         mmc_gl.cps.cur_host=0;
  449. }
  450.  
  451. /*
  452.  * if it is time, ask the server
  453.  */
  454. LDEF(void poll_server(void))
  455. {
  456.     set_event(EV_retrans,poll_server,
  457.         ((mmc_gl.cps.unans_queries>NUM_FAST_RETRIES)?POLL_TIME:RETRANS_MIN_TIME));
  458.     pick_server();
  459.  
  460.     GMS_send->gms_vers_maj=GMS_VERS_MAJ;
  461.     GMS_send->gms_vers_min=GMS_VERS_MIN;
  462.     GMS_send->gms_type=gms_ask_mail;
  463.     GMS_send->gms_id=mmc_gl.cps.seq_no++;
  464.     GMS_send->gms_poll_time=POLL_TIME;
  465.     strcpy(GMS_send->gms_text_buf,mmc_gl.cs.mmc_uname);
  466.  
  467.     gms_send(&ip_gl.mainpb);
  468. }
  469.  
  470. /*
  471.  * set text to ask server
  472.  * returns TRUE if no valid text found
  473.  */
  474. LDEF(void set_poll_name(mmc_state_pt s))
  475. {
  476.     int len=imin(MMC_uname_len-1,imax(0,strlen(s->mmc_uname)));
  477.  
  478.     if(memcmp(mmc_gl.cs.mmc_uname,s->mmc_uname,len+1)!=0)
  479.           mmc_gl.cps.change_count=0;
  480.  
  481.     memcpy(mmc_gl.cs.mmc_uname,s->mmc_uname,len);
  482.     mmc_gl.cs.mmc_uname[len]=0;
  483. }
  484.  
  485. LDEF(void update_flags(long new_flags))
  486. {
  487.     long old_flags=mmc_gl.cs.mmc_st;
  488.     mmc_gl.cs.mmc_st^=((old_flags^new_flags)&MCS_setable);
  489.     /*
  490.      * if no notification method is choosen
  491.      * default to posting a message
  492.      */
  493.     if(!gFLSET(MCS_nblink))
  494.         gTURN_ON_FLAGS(MCS_npost);
  495. }
  496.  
  497. /*
  498.  * initialize the world called from driver open routine
  499.  * return an os error code to not open
  500.  */
  501. int mmc_init()
  502. {
  503.     if(mmc_gl.cps.udp_buf!=0)        /*already initialized*/
  504.         return 0;
  505.     mmc_gl.cps.cur_host=TickCount()&1L;
  506.     mmc_note_init();
  507.     mmc_gl.cs.mmc_st_maj_ver=MMC_ST_maj_ver;
  508.     mmc_gl.cs.mmc_st_min_ver=MMC_ST_min_ver;
  509.     if((mmc_gl.cps.udp_buf=NewPtrSys(UDP_BUF_SIZE))==0)
  510.         return MMCE_noopen;
  511.     return 0;
  512. }
  513.  
  514. /*
  515.  * change the driver state call
  516.  */
  517. int mmc_set_state(s)
  518. mmc_state_pt s;
  519. {
  520.     int starting_up;
  521.     if(s->mmc_st_maj_ver!=MMC_ST_maj_ver)
  522.         return MMCE_bad_maj;
  523.     if(mmc_gl.cps.udp_buf==0)
  524.         return MMCE_noopen;
  525.  
  526.     update_flags(s->mmc_st);
  527.     mmc_gl.cs.mmc_check_num=s->mmc_check_num;
  528.  
  529.     mmc_gl.cs.mmc_remind_time=
  530.       imin(2*HOURS,imax(MIN_REMIND,s->mmc_remind_time));
  531.  
  532.     set_poll_name(s);
  533.     mmc_note_no_mail();
  534.  
  535.     strcpy(mmc_gl.cs.mmc_text_state,"New MailCheck configuration set");
  536.  
  537.     if((!gFLSET(MCS_want_open))||(mmc_gl.cs.mmc_uname[0]==0)||(FLSET(*s,MCS_snooze))) {
  538.         mmc_shutdown();                        /*set text state on shutdown*/
  539.         mmc_note_done();
  540.     } else
  541.       set_event(EV_retrans,mmc_start,0);
  542.  
  543.     if(FLSET(*s,MCS_snooze)) {
  544.       mmc_note_no_error();
  545.       strcpy(mmc_gl.cs.mmc_text_state,"45 min nap in progress");
  546.       set_event(EV_retrans,mmc_start,SNOOZE_TIME);
  547.     } else
  548.       mmc_note_sound_init(s->mmc_sound_id);
  549.  
  550.     return 0;
  551. }
  552.  
  553. /*
  554.  * convert an unsigned number to text
  555.  */
  556. static char *strunum(char *dst,long num);
  557. static char *strunum(dst,num)
  558. register char *dst;
  559. register long num;
  560. {
  561.     register long rem;
  562.     rem= num%10;
  563.     num/=10;
  564.     if(num!=0)
  565.       dst=strunum(dst,num);
  566.     *dst++ = '0'+rem;
  567.     *dst=0;
  568.     return dst;
  569. }
  570.  
  571. /*
  572.  * convert a signed number to text
  573.  */
  574. static void strnum(char *dst,long num);
  575. static void strnum(dst,num)
  576. register char *dst;
  577. register long num;
  578. {
  579.     if(num<0) {
  580.         *dst++='-';
  581.         num= -num;
  582.     }
  583.     strunum(dst,num);    
  584. }
  585.  
  586. /*
  587.  * convert a system error number to human readable text
  588.  */
  589. LDEF(void textify_syserr(char *dst,int ernum))
  590. {
  591.     switch(ernum) {
  592.     case 0:                /*not really an error*/
  593.         return;
  594.     case -43:
  595.         strcpy(dst,"The MacTCP driver does not seem to be installed.");
  596.         return;
  597.     case -23004:
  598.         strcpy(dst,
  599.           "A gateway is down or MacTCP isn't installed properly. If problem persists seek assistance.");
  600.         break;
  601.     case -23015:
  602.         strcpy(dst,
  603.             "The server host is up but it isn't running a MacCheck server.");
  604.         break;
  605.     case -23012:
  606.         strcpy(dst,
  607.             "The MacCheck server is not responding.  Perhaps a gateway just went down.");
  608.         break;
  609.     default:
  610.         strcpy(dst,
  611.             "Mac OS error code ");
  612.         strnum(dst+strlen(dst),ernum);
  613.     }
  614. }
  615.  
  616. /*
  617.  * set mmc_text state to have the text of the current error
  618.  */
  619. void textify_error(void)
  620. {
  621.     switch(mmc_gl.cs.mmc_last_err_kind) {
  622.     case MCE_NOERRR:
  623.         return;
  624.     case MCE_UDP_REL:
  625.         strcpy(mmc_gl.cs.mmc_text_state,"UDP dispose");
  626.         break;
  627.     case MCE_TOO_OLD:
  628.         strcpy(mmc_gl.cs.mmc_text_state,"MailCheck version too old to talk to server");
  629.         return;
  630.         break;
  631.     case MCE_UDP_READ:
  632.         strcpy(mmc_gl.cs.mmc_text_state,"UDP read");
  633.         break;
  634.     case MCE_UDP_CREATE:
  635.         strcpy(mmc_gl.cs.mmc_text_state,"UDP create");
  636.         break;
  637.     case MCE_MACTCP:
  638.         strcpy(mmc_gl.cs.mmc_text_state,"MacTCP open");
  639.         break;
  640.     case MCE_UDP_WRITE:
  641.         strcpy(mmc_gl.cs.mmc_text_state,"UDP write");
  642.         break;
  643.     case MCE_REM_ERR:
  644.         return;
  645.     case MCE_TIMEOUT:
  646.         strcpy(mmc_gl.cs.mmc_text_state,"MailCheck server does not respond");
  647.         return;
  648.     default:
  649.         strcpy(mmc_gl.cs.mmc_text_state,"Undefined internal error");
  650.         return;
  651.         break;
  652.     }
  653.     strcat(mmc_gl.cs.mmc_text_state," failed.   ");
  654.     textify_syserr(mmc_gl.cs.mmc_text_state+strlen(mmc_gl.cs.mmc_text_state),mmc_gl.cs.mmc_last_err_syserr);
  655. }
  656.  
  657. /*
  658.  * set a little bit of state, namely that macmail is running
  659.  */
  660. int mmc_setmmuser(mmc_state_pt s,mmc_priv_state_pt *active_priv_state)
  661. {
  662.   int err;
  663.   long want_snooze= s->mmc_st&MCS_snooze;
  664.   char new_user[MMC_uname_len];
  665.   memcpy(new_user,s->mmc_uname,MMC_uname_len);
  666.   if((err=mmc_get_state(s,active_priv_state)!=0))
  667.     return err;
  668.   s->mmc_st^= (s->mmc_st^want_snooze)&MCS_snooze;    /*set snooze accordingly*/
  669.   if((new_user[0]!=0)&&(gFLSET(MCS_hearmm)))
  670.     memcpy(s->mmc_uname,new_user,MMC_uname_len);
  671.   if((err=mmc_set_state(s))!=0)
  672.       return err;
  673.   return mmc_get_state(s,active_priv_state);
  674. }
  675.  
  676. /*
  677.  * return current state
  678.  */
  679. int mmc_get_state(old_state,active_priv_state)
  680. mmc_state_pt old_state;
  681. mmc_priv_state_pt *active_priv_state;
  682. {
  683.     if(old_state->mmc_st_maj_ver!=MMC_ST_maj_ver)
  684.         return MMCE_bad_maj;
  685.     textify_error();
  686.     *old_state=mmc_gl.cs;
  687.     if(mmc_gl.cs.mmc_last_err_kind==MCE_NOERRR)
  688.         old_state->mmc_st&= ~MCS_error;
  689.     else
  690.         old_state->mmc_st|= MCS_error;
  691.     *active_priv_state= &mmc_gl.cps;
  692.     return 0;
  693. }
  694.  
  695. /*
  696.  * mmc_tick - called periodicly to keep us happy
  697.  */
  698. void mmc_tick()
  699. {
  700.   if(mmc_gl.cps.udp_buf==0)
  701.       return;
  702.   if (gFLSET(MCS_io_pending))
  703.       poll_pb(&ip_gl.mainpb);
  704.   if(ip_gl.udp_stream!=0)
  705.     if ((!gFLSET(MCS_io_pending)) &&
  706.       (mmc_gl.cps.packet_waiting!=0))
  707.       act_read(&ip_gl.mainpb);
  708.  
  709.     {
  710.     register long now=TickCount();
  711.     register int i;
  712.     register mmc_event_pt ev= &mmc_gl.cps.ev[0];
  713.     for(i=0;(i<EV_NUM)&& !gFLSET(MCS_io_pending);i++,ev++)
  714.         if((now>=ev->ev_time)&&
  715.            (ev->ev_event!=0)) {
  716.              void (*the_event)(void)=ev->ev_event;
  717.              ev->ev_event=0;
  718.              (*(the_event))();
  719.              }
  720.    }
  721. }
  722.  
  723.